package archer.application.core.service.system;

import archer.application.core.entity.system.Menu;
import archer.application.core.entity.system.Role;
import archer.application.core.entity.system.RoleMenuRel;
import archer.application.core.entity.system.UserRoleRel;
import archer.application.core.entity.user.Staff;
import archer.application.core.entity.user.User;
import archer.framework.common.repository.condition.QueryCondition;
import archer.application.core.service.BaseService;
import archer.framework.protocol.result.ExecuteResult;
import archer.framework.utils.MapUtils;
import com.avaje.ebean.Query;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author christ
 * @date 2016/6/7
 */
@Service
public class RoleService extends BaseService {

    /**
     * 新增/保存角色
     *
     * @param role
     * @return
     */
    public ExecuteResult store(Role role) {

        if (isEmpty(role.getCode())) {
            throwParamNullException("角色编码不能为空");
        }

        if (isEmpty(role.getName())) {
            throwParamNullException("角色名称不能为空");
        }

        if (entityValidate(role).fail()) {
            throwParamInvalidateException(entityValidate(role).errorString());
        }

        if (role.duplicated("code")) {
            throwParamInvalidateException("角色编码不能重复");
        }

        if (role.duplicated("name")) {
            throwParamInvalidateException("角色名称不能重复");
        }

        if (isNotEmpty(role.getId())) {

            Role persisted = Role.find.byId(role.getId());

            if (isNotEmpty(persisted) && isY(persisted.getSysData()) && !persisted.getCode().equals(role.getCode())) {

                throwAccessDeniedException("系统内置数据的角色编码不能修改");
            }
        }

        return success(role.storeAndQuery());
    }

    /**
     * 删除角色
     */
    public ExecuteResult delete(String id) {

        if (isEmpty(id)) {

            throwParamNullException("角色不能为空");
        }

        Role role = Role.find.byId(id);

        if (isNotEmpty(role)) {

            if (isY(role.getSysData())) {

                throwAccessDeniedException("系统内置数据不能删除");
            }

            //删除用户角色对应的关联数据
            delete(
                    UserRoleRel.find
                            .query()
                            .where()
                            .eq("role.id", id)
                            .findList());
            //删除角色菜单的关联数据
            delete(
                    RoleMenuRel.find
                            .query()
                            .where()
                            .eq("role.id", id)
                            .findList()
            );

            //删除主表数据
            role.logicalDelete();

        }

        return success();
    }

    public ExecuteResult deleteAll(List<String> ids) {

        for (String each : ids) {
            this.delete(each);
        }

        return success();
    }

    /**
     * 查找角色
     *
     * @param id
     * @return
     */
    public ExecuteResult find(String id) {

        if (isEmpty(id)) {
            throwParamNullException("角色不能为空");
        }

        return success(Role.find.byId(id));
    }

    /**
     * 分页查询所有角色
     */
    public ExecuteResult findPagedList(QueryCondition queryCondition) {

        return success(findPagedList(Role.find.query(), queryCondition));
    }


    /**
     * 分页查询属于某个角色的用户列表
     *
     * @param queryCondition
     * @param id
     * @return
     */
    public ExecuteResult findSelectedStaffPagedList(String id, QueryCondition queryCondition) {

        if (isEmpty(id)) {
            throwParamNullException("角色不能为空");
        }

        return success(
                findPagedList(Staff.find
                        .query()
                        .where()
                        .eq("userRoleRels.role.id", id)
                        .query(), queryCondition)
        );
    }

    /**
     * 分页查询不属于某个角色的用户列表
     *
     * @param id
     * @param queryCondition
     * @return
     */
    public ExecuteResult findUnselectedStaffPagedList(String id, QueryCondition queryCondition) {

        if (isEmpty(id)) {
            throwParamNullException("角色不能为空");
        }

        Query subQuery = UserRoleRel.find.query().select("staff.id").where().eq("role.id", id).query();

        return success(findPagedList(User.find
                .query()
                .where()
                .notIn("id", subQuery)
                .query(), queryCondition));

    }

    /**
     * 分配用户角色关系
     *
     * @param id
     * @param userIds
     * @return
     */
    public ExecuteResult assignUsers(String id, List<String> userIds) {

        if (isEmpty(id)) {
            throwParamNullException("角色不能为空");
        }

        if (isNotEmpty(userIds)) {

            List<UserRoleRel> userRoles = new ArrayList<>();
            for (String each : userIds) {
                userRoles.add(new UserRoleRel().setRoleId(id).setUserId(each));
            }

            store(userRoles);
        }

        return success();
    }


    /**
     * 移除用户角色关系
     *
     * @param id
     * @param userIds
     * @return
     */
    public ExecuteResult unAssignUsers(String id, List<String> userIds) {

        if (isEmpty(id)) {
            throwParamNullException("角色不能为空");
        }

        if (isNotEmpty(userIds)) {

            delete(UserRoleRel.find
                            .query()
                            .where()
                            .eq("role.id", id)
                            .in("staff.id", userIds)
                            .findList()
            );
        }

        return success();
    }

    /**
     * 获得选中的菜单列表
     *
     * @param id
     * @return
     */
    public ExecuteResult findSelectedMenus(String id) {

        if (isEmpty(id)) {
            throwParamNullException("角色不能为空");
        }

        List<Menu> menus = Menu.find.query().where().orderBy("sort").findList();

        if (isEmpty(menus)) {
            return success(emptyList());
        }

        List<RoleMenuRel> selectedMenus = RoleMenuRel.find.query().where().eq("role.id", id).findList();

        if (isNotEmpty(selectedMenus)) {
            Map map = MapUtils.groupByFields(selectedMenus, "menu.id");
            for (Menu each : menus) {
                if (map.containsKey(each.getId())) {
                    each.setChecked(true);
                }
            }
        }

        return success(menus);
    }

    /**
     * 分配菜单给某个角色
     *
     * @param id
     * @param menuIds
     * @return
     */
    public ExecuteResult assignMenus(String id, List<String> menuIds) {

        if (isEmpty(id)) {
            throwParamNullException("角色不能为空");
        }

        //移除原有的菜单角色对应关系
        List<RoleMenuRel> roleMenuRels = RoleMenuRel.find.query().where().eq("role.id", id).findList();
        if (isNotEmpty(roleMenuRels)) {
            delete(roleMenuRels);
        }

        //新增新的关系
        if (isNotEmpty(menuIds)) {
            for (String menuId : menuIds) {

                RoleMenuRel roleMenuRel = RoleMenuRel.find.query().where()
                        .eq("menu.id", menuId)
                        .eq("role.id", id)
                        .findUnique();

                if (isEmpty(roleMenuRel)) {
                    new RoleMenuRel().setMenuId(menuId).setRoleId(id).store();
                }
            }
        }

        return success();
    }

}
